<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Service;

use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Model\Question;
use App\Service\Dao\QuestionDao;
use App\Service\Dao\UserDao;
use App\Service\Search\QuestionSearch;
use Hyperf\AsyncQueue\Annotation\AsyncQueueMessage;
use Hyperf\Di\Annotation\Inject;
use HyperfX\Utils\Service;

class QuestionService extends Service
{
    /**
     * @Inject
     * @var CategoryService
     */
    protected $category;

    /**
     * @Inject
     * @var QuestionDao
     */
    protected $dao;

    /**
     * @Inject
     * @var QuestionSearch
     */
    protected $search;

    /**
     * @param $input = [
     *     'title' => '', // 标题
     *     'category_id' => 1, // 分类ID
     *     'summary' => '', // 问题详情
     * ]
     */
    public function publish(int $id, int $userId, array $input): Question
    {
        if (! $this->category->isExist($input['category_id'])) {
            throw new BusinessException(ErrorCode::CATEGORY_INVALID);
        }
        $user = di()->get(UserDao::class)->firstCache($userId, true);
        if ($id > 0) {
            $model = $this->dao->firstCache($id, true);
            if ($model->user_id !== $user->id) {
                throw new BusinessException(ErrorCode::OPERATION_INVALID);
            }
        } else {
            $model = new Question();
            $model->user_id = $user->id;
            $model->status = Question::STATUS_ONLINE;
        }
        $model->category_id = $input['category_id'];
        $model->title = $input['title'];
        $model->summary = $input['summary'];
        $model->save();

        return $model;
    }

    public function delete(int $id, int $userId)
    {
        $user = di()->get(UserDao::class)->firstCache($userId, true);
        $model = $this->dao->firstCache($id, true);

        if ($model->user_id !== $user->id) {
            throw new BusinessException(ErrorCode::OPERATION_INVALID);
        }

        $model->status = Question::STATUS_DELETED;
        return $model->save();
    }

    /**
     * @AsyncQueueMessage(delay=5, maxAttempts=5)
     */
    public function putToSearch(int $id)
    {
        $model = $this->dao->first($id);
        if (! $model) {
            $this->logger->error(sprintf('Question[%d] is not exists.', $id));
        }

        $this->search->put($model);
        $this->logger->info(sprintf('Question[%d] put to search success.', $id));
    }

    /**
     * @param $input = [
     *     'category_id' => 1, // 分类ID
     *     'keyword' => '', // 关键字
     *     'user_id' => 0, // 用户ID
     * ]
     * @param mixed $offset
     * @param mixed $limit
     */
    public function search(array $input = [], int $offset = 0, int $limit = 10)
    {
        $body = [];
        $body['bool']['must'][] = ['term' => ['status' => Question::STATUS_ONLINE]];
        if (isset($input['category_id'])) {
            $body['bool']['must'][] = ['term' => ['category_id' => $input['category_id']]];
        }

        [$count, $res] = $this->search->search([
            'query' => (object) $body,
            'from' => $offset,
            'size' => $limit,
        ]);

        $models = $this->dao->findMany($res);
        $models->loadCache(['user', 'category']);

        return [$count, $models];
    }
}
